package com.ecarx.camera.worker.car.aosp;

import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;
import android.util.SparseIntArray;

import com.ecarx.camera.utils.LogUtils;
import com.ecarx.camera.worker.car.ICarFunctionProxy;
import com.ecarx.camera.worker.car.ICarSensorProxy;
import com.ecarx.camera.worker.car.adaptapi.AdaptWrapperHelper;

import java.util.ArrayList;
import java.util.List;

/**
 * Aosp原生CarPropertyEventCallback封装类
 */
class PropertyEventCallbackWrapper implements CarPropertyManager.CarPropertyEventCallback {

    private static final String TAG = "PropertyEventCallbackWrapper";

    private ICarFunctionProxy.IFunctionValueWatcher mFunctionValueWatcher;
    private ICarSensorProxy.ISensorListener mSensorListener;

    /**
     * key为AdaptAPI的functionId或sensorId，value为AOSP对应的PropertyId
     */
    private final SparseIntArray mRegisteredId = new SparseIntArray();

    public PropertyEventCallbackWrapper(ICarFunctionProxy.IFunctionValueWatcher functionValueWatcher) {
        this.mFunctionValueWatcher = functionValueWatcher;
    }

    public PropertyEventCallbackWrapper(ICarSensorProxy.ISensorListener sensorListener) {
        this.mSensorListener = sensorListener;
    }

    /**
     * 添加注册成功的Id
     * @param functionIdOrSensorId AdaptAPI的functionId或sensorId
     * @param propId Aosp对应的propId
     */
    public void addRegisteredId(int functionIdOrSensorId, int propId) {
        mRegisteredId.put(functionIdOrSensorId, propId);
    }

    /**
     * 清空相关数据
     */
    public void clear() {
        mRegisteredId.clear();
    }

    /**
     * 判断是否有注册成功的Id
     * @return
     */
    public boolean hasRegisteredId() {
        return mRegisteredId.size() > 0;
    }

    @Override
    public void onChangeEvent(CarPropertyValue carPropertyValue) {
        int propId = carPropertyValue.getPropertyId();
        int index = mRegisteredId.indexOfValue(propId);
        LogUtils.d(TAG, "onChangeEvent: " + carPropertyValue + ", index:" + index + ", propId:" + propId);
        if (index < 0) {
            return;
        }
        int areaId = carPropertyValue.getAreaId();
        Object value = carPropertyValue.getValue();
        int status = carPropertyValue.getStatus();
        int functionStatus = AospPropertyMapping.getFunctionStatus(status);
        int functionOrSensorId = mRegisteredId.keyAt(index);
        LogUtils.d(TAG, "onChangeEvent, propId:" + propId + ", functionOrSensorId:" + functionOrSensorId + ", status:" + status + ", functionStatus:" + functionStatus + ", index:" + index);

        if (mFunctionValueWatcher != null) {
            if (isIntegerValue(value)) {
                mFunctionValueWatcher.onFunctionChanged(functionOrSensorId);
                int adaptValue = AdaptWrapperHelper.propertyValueToFunctionValue(functionOrSensorId, (Integer) value);
                mFunctionValueWatcher.onFunctionValueChanged(functionOrSensorId, areaId, adaptValue);
            }
            if (isFloatValue(value)) {
                mFunctionValueWatcher.onFunctionChanged(functionOrSensorId);
                mFunctionValueWatcher.onFunctionFloatValueChanged(functionOrSensorId, areaId, (Float) value);
            }
            if (isBooleanValue(value)) {
                mFunctionValueWatcher.onFunctionChanged(functionOrSensorId);
                mFunctionValueWatcher.onFunctionBooleanValueChanged(functionOrSensorId, areaId, (Boolean) value);
            }
            mFunctionValueWatcher.onFunctionSupportedChanged(functionOrSensorId, areaId, functionStatus);
        }

        if (mSensorListener != null) {
            if (isIntegerValue(value)) {
                int adaptValue = AdaptWrapperHelper.propertyValueToSensorValue(functionOrSensorId, (Integer) value);
                mSensorListener.onSensorEventChanged(functionOrSensorId, adaptValue);
            }
            if (isFloatValue(value)) {
                mSensorListener.onSensorValueChanged(functionOrSensorId, (Float) value);
            }
            mSensorListener.onSensorSupportedChanged(functionOrSensorId, functionStatus);
        }
    }

    @Override
    public void onErrorEvent(int propId, int zone) {
        LogUtils.w(TAG, "CarPropertyEventCallback onErrorEvent propId:" + propId + ", zone:" + zone);
    }

    private static boolean isIntegerValue(Object obj){
        final Class cls = obj == null ? null : obj.getClass();
        return Integer.class == cls || int.class == cls;
    }

    private static boolean isFloatValue(Object obj){
        final Class cls = obj == null ? null : obj.getClass();
        return Float.class == cls || float.class == cls;
    }

    private static boolean isBooleanValue(Object obj){
        final Class cls = obj == null ? null : obj.getClass();
        return Boolean.class == cls || boolean.class == cls;
    }
}
